﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using XcoAppSpaces.Core.Ports;
using XcoAppSpaces.Security.Basic;
using XcoAppSpaces.Contracts.Security;
using XcoAppSpaces.Contracts.Service;
using test.XcoAppSpaces.Security.Basic.Helpers;

namespace test.XcoAppSpaces.Security.Basic
{
	class MyType
	{
	}
	class MySubType : MyType
	{
	}

	class SinglePortWorker : Port<string>
	{
	}

	[TestFixture]
	public class testWorkerPermissionInfo
	{
		private string role1;
		private string role2;
		private string role3;
		private XcoSecurityPermissionAttribute secAttr1;
		private XcoSecurityPermissionAttribute secAttr2;
		private XcoSecurityPermissionAttribute secAttr3;
		private IPort worker;
		private WorkerPermissionInfo permInfo;
		
		[SetUp]
		public void SetUp()
		{
			role1 = "role1";
			role2 = "role2";
			role3 = "role3";
			secAttr1 = new XcoSecurityPermissionAttribute(role1);
			secAttr2 = new XcoSecurityPermissionAttribute(role2);
			secAttr3 = new XcoSecurityPermissionAttribute(role3);
			
			worker = new PortSet<int, string, MyType>();
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr1, WorkerMessageType = null},
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(int)},
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(MyType)},
				new XcoServiceAttributeInfo{Attr = secAttr3, WorkerMessageType = typeof(MyType)}},
				new LoggerMockup());

		}

		[Test]
		public void TestAssignedRoles()
		{
			Assert.AreEqual(1, permInfo.WorkerRoles.Count);
			Assert.Contains(role1, permInfo.WorkerRoles);

			Assert.AreEqual(3, permInfo.PortRoles.Count);
			Assert.Contains(typeof(int), permInfo.PortRoles.Keys);
			Assert.Contains(typeof(string), permInfo.PortRoles.Keys);
			Assert.Contains(typeof(MyType), permInfo.PortRoles.Keys);

			Assert.AreEqual(1, permInfo.PortRoles[typeof(int)].Count);
			Assert.AreEqual(0, permInfo.PortRoles[typeof(string)].Count);
			Assert.AreEqual(2, permInfo.PortRoles[typeof(MyType)].Count);
		}

		[Test]
		public void TestAllowedMessageTypes_Role1()
		{
			User user = new User("test", new byte[] { }, role1);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(3, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_Role2()
		{
			User user = new User("test", new byte[] { }, role2);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(2, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			//Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_Role3()
		{
			User user = new User("test", new byte[] { }, role3);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(1, allowed.Count);
			//Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_Role2And3()
		{
			User user = new User("test", new byte[] { }, role2, role3);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(2, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			//Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoRoles()
		{
			User user = new User("test", new byte[] { });
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(0, allowed.Count);
			//Assert.Contains(typeof(string), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoUser()
		{
			List<Type> allowed = permInfo.GetAllowedMessageTypes(null);

			Assert.IsNull(allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoSec_AnyUser()
		{
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>(), new LoggerMockup());
			User user = new User("test", new byte[] { });
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(3, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoSec_NoUser()
		{
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>(), new LoggerMockup());
			List<Type> allowed = permInfo.GetAllowedMessageTypes(null);

			Assert.AreEqual(3, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoWorkerRoles_UserRole2()
		{
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(int)},
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(MyType)},
				new XcoServiceAttributeInfo{Attr = secAttr3, WorkerMessageType = typeof(MyType)}},
				new LoggerMockup());
			User user = new User("test", new byte[] { }, role2);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(3, allowed.Count);
			Assert.Contains(typeof(int), allowed);
			Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoWorkerRoles_UserRole3()
		{
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(int)},
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(MyType)},
				new XcoServiceAttributeInfo{Attr = secAttr3, WorkerMessageType = typeof(MyType)}},
				new LoggerMockup());
			User user = new User("test", new byte[] { }, role3);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(2, allowed.Count);
			Assert.Contains(typeof(string), allowed);
			Assert.Contains(typeof(MyType), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_NoWorkerRoles_NoUserRoles()
		{
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(int)},
				new XcoServiceAttributeInfo{Attr = secAttr2, WorkerMessageType = typeof(MyType)},
				new XcoServiceAttributeInfo{Attr = secAttr3, WorkerMessageType = typeof(MyType)}},
				new LoggerMockup());
			User user = new User("test", new byte[] { });
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(1, allowed.Count);
			Assert.Contains(typeof(string), allowed);
		}


		[Test]
		public void TestAllowedMessageTypes_SinglePortWorker_Role1()
		{
			worker = new SinglePortWorker();
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr1, WorkerMessageType = typeof(string)}},
				new LoggerMockup());
			User user = new User("test", new byte[] { }, role1);
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(1, allowed.Count);
			Assert.Contains(typeof(string), allowed);
		}

		[Test]
		public void TestAllowedMessageTypes_SinglePortWorker_NoRoles()
		{
			worker = new SinglePortWorker();
			permInfo = new WorkerPermissionInfo(worker, new List<XcoServiceAttributeInfo>{
				new XcoServiceAttributeInfo{Attr = secAttr1, WorkerMessageType = typeof(string)}},
				new LoggerMockup());
			User user = new User("test", new byte[] { });
			List<Type> allowed = permInfo.GetAllowedMessageTypes(user);

			Assert.AreEqual(0, allowed.Count);
		}
	}
}
